package com.kool.kmqtt.server.packet;

import com.kool.kmqtt.server.exception.ErrorCode;
import com.kool.kmqtt.server.exception.ProtocolException;
import lombok.Data;

@Data
public class FixedHeader {
    /**
     * MQTT控制报文的类型
     *
     * @see com.kool.kmqtt.server.constant.PacketTypeEnum
     */
    private int packetType;
    /**
     * 用于指定控制报文类型的标志位
     */
    private int flags;

    /**
     * 设置重发标志
     *
     * @param dup
     */
    public void setDup(boolean dup) {
        flags = dup ? flags | 0x08 : flags & 0x07;
    }

    public boolean getDup() {
        return flags >> 3 == 1;
    }

    /**
     * 设置qos
     *
     * @param qos
     */
    public void setQoS(int qos) {
        flags = flags & 0x09 + qos << 1;
    }

    public int getQoS() {
        return flags & 0x07 >> 1;
    }

    /**
     * 设置保留标志
     *
     * @param retain
     */
    public void setRetain(boolean retain) {
        flags = retain ? flags | 0x01 : flags & 0x0e;
    }

    public boolean getRetain() {
        return (flags & 0x01) == 1;
    }

    /**
     * 剩余长度
     */
    private int remainingLength;

    /**
     * 编码
     *
     * @return
     */
    public byte[] toBytes() {
        byte[] buff = new byte[5];

        buff[0] = (byte) ((packetType << 4) + flags);

        int x = remainingLength;
        //可变报头+载荷的最大允许长度为256MB，0xFF,0xFF,0xFF,0x7F
        if (remainingLength > 268435455) {
            throw new ProtocolException(ErrorCode.MAX_LENGTH_ERROR);
        }
        int i = 1;
        if (remainingLength == 0) {
            buff[1] = 0;
            i = 2;
        } else {
            while (x > 0) {
                //取字节的低7位
                byte byteN = (byte) (x & 0x7f);

                //除以128
                x = x >> 7;
                if (x > 0) {
                    //如果有余数，延续位置1
                    byteN = (byte) (byteN | 128);
                }
                buff[i] = byteN;
                i++;
            }
        }
        byte[] bytes = new byte[i];
        System.arraycopy(buff, 0, bytes, 0, i);
        return bytes;
    }
}
